package fr.sedoo.commons.client.widget.map.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.view.client.CellPreviewEvent;
import com.google.gwt.view.client.CellPreviewEvent.Handler;

import fr.sedoo.commons.client.image.CommonBundle;
import fr.sedoo.commons.client.message.CommonMessages;
import fr.sedoo.commons.client.message.GeographicalMessages;
import fr.sedoo.commons.client.util.StringUtil;
import fr.sedoo.commons.client.util.UuidUtil;
import fr.sedoo.commons.client.widget.table.AbstractListTable;
import fr.sedoo.commons.client.widget.table.ImagedActionCell;
import fr.sedoo.commons.client.widget.table.WaterMarkCell;
import fr.sedoo.commons.shared.domain.GeographicBoundingBoxDTO;
import fr.sedoo.commons.shared.domain.HasIdentifier;

public class MultipleAreaTable extends AbstractListTable implements RectangularAreaListener {

	private AreaSelectorWidget areaSelector;

	private Image zoomImage = new Image(CommonBundle.INSTANCE.zoom());

	public MultipleAreaTable(AreaSelectorWidget areaSelector) {
		super();
		init(new ArrayList<HasIdentifier>());
		this.areaSelector = areaSelector;
		areaSelector.addListener(this);
		setAskDeletionConfirmation(false);
		setAddButtonEnabled(true);

		itemTable.addCellPreviewHandler(new Handler<HasIdentifier>() {
			@Override
			public void onCellPreview(CellPreviewEvent<HasIdentifier> event) {
				if (BrowserEvents.MOUSEOVER.equals(event.getNativeEvent().getType())) {
					getAreaSelector().hover(event.getValue().getIdentifier());
				} else if (BrowserEvents.MOUSEOUT.equals(event.getNativeEvent().getType())) {
					getAreaSelector().unhover(event.getValue().getIdentifier());
				}
			}
		});
	}

	public AreaSelectorWidget getAreaSelector() {
		return areaSelector;
	}

	@Override
	public void addItem() {
		addRow(null);
	}

	@Override
	public String getAddItemText() {
		return GeographicalMessages.INSTANCE.addAnArea();
	}

	@Override
	public void presenterDelete(HasIdentifier hasId) {
		String identifier = hasId.getIdentifier();
		removeRow(identifier);
		areaSelector.destroy(identifier);
	}

	@Override
	public void presenterEdit(HasIdentifier hasId) {
		// presenter.editDrainageBasin(id);
		// System.out.println("edit");

	}

	@Override
	protected void initColumns() {
		// Nothing is done there
	}

	@Override
	public void onRectangleAdded(GeographicBoundingBoxDTO box) {
		if (!isPresent(box.getIdentifier())) {
			addRow(box);
		}
	}

	private boolean isPresent(String uuid) {
		Iterator<? extends HasIdentifier> iterator = getModel().iterator();
		while (iterator.hasNext()) {
			HasIdentifier hasIdentifier = iterator.next();
			if (hasIdentifier.getIdentifier().compareTo(uuid) == 0) {
				return true;
			}
		}
		return false;
	}

	// private void updateSiteListener(SiteDTO site) {
	// if ((!StringUtil.isEmpty(site.getLatitude())) &&
	// (!StringUtil.isEmpty(site.getLongitude()))) {
	// if ((DoubleUtil.checkDouble(site.getLatitude())) &&
	// (DoubleUtil.checkDouble(site.getLongitude()))) {
	// siteEventListener.siteAdded(site);
	// }
	// }
	// }

	private void addRow(GeographicBoundingBoxDTO box) {
		List<GeographicBoundingBoxDTO> newValues = new ArrayList<GeographicBoundingBoxDTO>();
		Iterator<? extends HasIdentifier> iterator = model.iterator();
		while (iterator.hasNext()) {
			GeographicBoundingBoxDTO aux = (GeographicBoundingBoxDTO) iterator.next();
			newValues.add(aux);
		}

		if (box != null) {
			if (box.getIdentifier() == null) {
				box.setIdentifier(UuidUtil.uuid());
			}
			newValues.add(box);
		} else {
			GeographicBoundingBoxDTO empty = new GeographicBoundingBoxDTO();
			empty.setIdentifier(UuidUtil.uuid());
			newValues.add(empty);
		}

		init(newValues);

	}

	@Override
	public void onRectangleUpdated(GeographicBoundingBoxDTO box) {
		// We dont manage this case

	}

	@Override
	public void onRectangleDeleted(String uuid) {
		if (isPresent(uuid))
			removeRow(uuid);
	}

	public ArrayList<GeographicBoundingBoxDTO> getBoxes() {
		ArrayList<GeographicBoundingBoxDTO> result = new ArrayList<GeographicBoundingBoxDTO>();
		Iterator<? extends HasIdentifier> iterator = model.iterator();
		while (iterator.hasNext()) {
			GeographicBoundingBoxDTO box = (GeographicBoundingBoxDTO) iterator.next();
			if (box.isValid()) {
				result.add(box);
			}
		}
		return result;
	}

	public void setBoxes(ArrayList<GeographicBoundingBoxDTO> boxes) {
		if (model != null) {
			ArrayList<String> identifiers = new ArrayList<String>();
			Iterator<? extends HasIdentifier> iterator = model.iterator();
			while (iterator.hasNext()) {
				identifiers.add(iterator.next().getIdentifier());
			}

			Iterator<String> identifiersIterator = identifiers.iterator();
			while (identifiersIterator.hasNext()) {
				removeRow(identifiersIterator.next());
			}

		}
		Iterator<GeographicBoundingBoxDTO> iterator2 = boxes.iterator();
		while (iterator2.hasNext()) {
			GeographicBoundingBoxDTO box = iterator2.next();
			addRow(box);
			areaSelector.add(box);
		}
	}

	protected ImagedActionCell.Delegate<HasIdentifier> zoomAction = new ImagedActionCell.Delegate<HasIdentifier>() {
		@Override
		public void execute(final HasIdentifier hasId) {
			areaSelector.zoomTo(hasId.getIdentifier());
		}
	};

	public void enableDisplayColumn() {
		clearColumns();
		Column<HasIdentifier, String> eastLongitudeDisplay = new Column<HasIdentifier, String>(new TextCell()) {
			@Override
			public String getValue(HasIdentifier box) {
				return StringUtil.trimToEmpty(((GeographicBoundingBoxDTO) box).getEastBoundLongitude());
			}
		};

		Column<HasIdentifier, String> westLongitudeDisplay = new Column<HasIdentifier, String>(new TextCell()) {
			@Override
			public String getValue(HasIdentifier box) {
				return StringUtil.trimToEmpty(((GeographicBoundingBoxDTO) box).getWestBoundLongitude());
			}
		};

		Column<HasIdentifier, String> northLatitudeDisplay = new Column<HasIdentifier, String>(new TextCell()) {
			@Override
			public String getValue(HasIdentifier box) {
				return StringUtil.trimToEmpty(((GeographicBoundingBoxDTO) box).getNorthBoundLatitude());
			}
		};

		Column<HasIdentifier, String> southLatitudeDisplay = new Column<HasIdentifier, String>(new TextCell()) {
			@Override
			public String getValue(HasIdentifier box) {
				return StringUtil.trimToEmpty(((GeographicBoundingBoxDTO) box).getSouthBoundLatitude());
			}
		};

		itemTable.setColumnWidth(northLatitudeDisplay, 50.0, Unit.PX);
		itemTable.addColumn(northLatitudeDisplay, GeographicalMessages.INSTANCE.mapSelectorNorthLatitude());

		itemTable.setColumnWidth(eastLongitudeDisplay, 50.0, Unit.PX);
		itemTable.addColumn(eastLongitudeDisplay, GeographicalMessages.INSTANCE.mapSelectorEastLongitude());

		itemTable.setColumnWidth(southLatitudeDisplay, 50.0, Unit.PX);
		itemTable.addColumn(southLatitudeDisplay, GeographicalMessages.INSTANCE.mapSelectorSouthLatitude());

		itemTable.setColumnWidth(westLongitudeDisplay, 50.0, Unit.PX);
		itemTable.addColumn(westLongitudeDisplay, GeographicalMessages.INSTANCE.mapSelectorWestLongitude());

		Cell<HasIdentifier> zoomActionCell = new ImagedActionCell<HasIdentifier>(zoomAction, zoomImage, CommonMessages.INSTANCE.zoom());
		Column<HasIdentifier, String> zoomColumn = new Column(zoomActionCell) {

			@Override
			public HasIdentifier getValue(Object object) {
				return (HasIdentifier) object;
			}
		};

		itemTable.addColumn(zoomColumn);
		itemTable.setColumnWidth(zoomColumn, 30.0, Unit.PX);
	}

	public void enableEditColumn() {
		clearColumns();
		Column<HasIdentifier, String> eastLongitude = new Column<HasIdentifier, String>(new WaterMarkCell(GeographicalMessages.INSTANCE.mapSelectorEastLongitude(), "10", "10")) {
			@Override
			public String getValue(HasIdentifier box) {
				return StringUtil.trimToEmpty(((GeographicBoundingBoxDTO) box).getEastBoundLongitude());
			}
		};

		eastLongitude.setFieldUpdater(new FieldUpdater<HasIdentifier, String>() {
			@Override
			public void update(int index, HasIdentifier box, String longitude) {
				GeographicBoundingBoxDTO aux = (GeographicBoundingBoxDTO) box;
				aux.setEastBoundLongitude(longitude);
				areaSelector.update(aux);
			}
		});

		Column<HasIdentifier, String> westLongitude = new Column<HasIdentifier, String>(new WaterMarkCell(GeographicalMessages.INSTANCE.mapSelectorWestLongitude(), "10", "10")) {
			@Override
			public String getValue(HasIdentifier box) {
				return StringUtil.trimToEmpty(((GeographicBoundingBoxDTO) box).getWestBoundLongitude());
			}
		};

		westLongitude.setFieldUpdater(new FieldUpdater<HasIdentifier, String>() {
			@Override
			public void update(int index, HasIdentifier box, String longitude) {
				GeographicBoundingBoxDTO aux = (GeographicBoundingBoxDTO) box;
				aux.setWestBoundLongitude(longitude);
				areaSelector.update(aux);
			}
		});

		Column<HasIdentifier, String> northLatitude = new Column<HasIdentifier, String>(new WaterMarkCell(GeographicalMessages.INSTANCE.mapSelectorNorthLatitude(), "10", "10")) {
			@Override
			public String getValue(HasIdentifier box) {
				return StringUtil.trimToEmpty(((GeographicBoundingBoxDTO) box).getNorthBoundLatitude());
			}
		};

		northLatitude.setFieldUpdater(new FieldUpdater<HasIdentifier, String>() {
			@Override
			public void update(int index, HasIdentifier box, String latitude) {
				GeographicBoundingBoxDTO aux = (GeographicBoundingBoxDTO) box;
				aux.setNorthBoundLatitude(latitude);
				areaSelector.update(aux);
			}
		});

		Column<HasIdentifier, String> southLatitude = new Column<HasIdentifier, String>(new WaterMarkCell(GeographicalMessages.INSTANCE.mapSelectorSouthLatitude(), "10", "10")) {
			@Override
			public String getValue(HasIdentifier box) {
				return StringUtil.trimToEmpty(((GeographicBoundingBoxDTO) box).getSouthBoundLatitude());
			}
		};

		southLatitude.setFieldUpdater(new FieldUpdater<HasIdentifier, String>() {
			@Override
			public void update(int index, HasIdentifier box, String latitude) {
				GeographicBoundingBoxDTO aux = (GeographicBoundingBoxDTO) box;
				aux.setSouthBoundLatitude(latitude);
				areaSelector.update(aux);
			}
		});

		Cell<HasIdentifier> zoomActionCell = new ImagedActionCell<HasIdentifier>(zoomAction, zoomImage, CommonMessages.INSTANCE.zoom());
		Column<HasIdentifier, String> zoomColumn = new Column(zoomActionCell) {

			@Override
			public HasIdentifier getValue(Object object) {
				return (HasIdentifier) object;
			}
		};

		itemTable.setColumnWidth(northLatitude, 50.0, Unit.PX);
		itemTable.addColumn(northLatitude, GeographicalMessages.INSTANCE.mapSelectorNorthLatitude());

		itemTable.setColumnWidth(eastLongitude, 50.0, Unit.PX);
		itemTable.addColumn(eastLongitude, GeographicalMessages.INSTANCE.mapSelectorEastLongitude());

		itemTable.setColumnWidth(southLatitude, 50.0, Unit.PX);
		itemTable.addColumn(southLatitude, GeographicalMessages.INSTANCE.mapSelectorSouthLatitude());

		itemTable.setColumnWidth(westLongitude, 50.0, Unit.PX);
		itemTable.addColumn(westLongitude, GeographicalMessages.INSTANCE.mapSelectorWestLongitude());

		itemTable.addColumn(deleteColumn);
		itemTable.setColumnWidth(deleteColumn, 30.0, Unit.PX);

		itemTable.addColumn(zoomColumn);
		itemTable.setColumnWidth(zoomColumn, 30.0, Unit.PX);
	}

	// @Override
	// public void siteRemoved(String id) {
	// removeRow(id);
	// }
	//
	//
	//
	// public SiteEventListener getSiteEventListener() {
	// return siteEventListener;
	// }
	//
	// public void setSiteEventListener(SiteEventListener siteEventListener) {
	// this.siteEventListener = siteEventListener;
	// }
	//
	// public List<SiteDTO> getSiteDTOs() {
	// List<SiteDTO> result = new ArrayList<SiteDTO>();
	// Iterator<? extends HasIdentifier> iterator = model.iterator();
	// while (iterator.hasNext()) {
	// SiteDTO aux = (SiteDTO) iterator.next();
	// result.add(aux);
	// }
	// return result;
	// }

}
